#pragma once

#include <list>
#include <map>

#include "Globals.h"
#include "GameObject.h"
#include "Size.h"

#define MAX_KEYS 256

namespace game_engine
{

/*!
 * \class Scene
 * \brief 
 */
class Scene
{
///////////////////////////////////////////////////////////////////////////////
// Attribute definition
///////////////////////////////////////////////////////////////////////////////
protected:
  	BOOL keys[MAX_KEYS];
    string name;
    utils::Size resolution;
    GameObject *activeCamera;
    list<GameObject*> objects;
    map<string, GameObject*> objectsByName;
    map<INT32, utils::Point> mouseButtonUp;
    map<INT32, utils::Point> mouseButtonDown;
    Scene *nextScene;

///////////////////////////////////////////////////////////////////////////////
// Method definition
///////////////////////////////////////////////////////////////////////////////
public:
    // Constructors and Destructors
    Scene(void);
    Scene(const string &n);
    virtual ~Scene(void);

    // Others
    void addObject(GameObject *newObj);
    void removeObject(GameObject *obj);
    void removeObject(const string &objName);
    const BOOL keyPressed(const UINT32 key) const;
    void forceKeyState(const UINT32 key, const BOOL pressed);
    const BOOL isButtonUp(const INT32 button, utils::Point &position);
    const BOOL isButtonDown(const INT32 button, utils::Point &position);

    virtual const BOOL initialize(void);
	virtual const BOOL loop(void);
	virtual void finalize(void);
	virtual void readKeyboard(const UCHAR key, const INT32 x, 
        const INT32 y, const BOOL press);
	virtual void readMouse(const INT32 button, const INT32 state, 
        const INT32 x, const INT32 y);
	virtual void render(void);

    // Getters
    const string& getName(void) const;
    const utils::Size& getResolution(void) const;
    GameObject* getActiveCamera(void) const;
    const list<GameObject*> getObjects(void) const;
    GameObject* getObjectByName(const string &objName) const throw(...);
    //vector<GameObject*> getObjectsByTag(const string &tagName) const;
    Scene* getNextScene(void) const;

    // Setters
    void setName(const string &n);
    void setResolution(const utils::Size &res);
    void setActiveCamera(GameObject *cam);

protected:
    virtual const BOOL update(const FLOAT32 time) = 0;
    void initGameObjects(void) throw(...);
    void updateGameObjects(const FLOAT32 time) throw(...);
    void renderGameObjects(void) throw(...);
    void finishGameObjects(void) throw(...);

private:
    const BOOL findObject(const string &objName, 
        map<string, GameObject*>::const_iterator &it) const;

};

}

